/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
					     dialog_tree_of_knowledge.cpp

	$Header: /game/dialog_tree_of_knowledge.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "dialog_tree_of_knowledge.h"

#include "adaptor_handler.h"
#include "adv_tree_of_knowledge.h"
#include "army.h"
#include "basic_dialog.h"
#include "bitmap_group.h"
#include "bitmap_group_cache.h"
#include "bitmap_group_ptr.h"
#include "bitmap_group_window.h"
#include "bitmap_layer.h"
#include "bitmap_layer_window.h"
#include "bound_handler.h"
#include "button.h"
#include "button_cache.h"
#include "creature_select_window.h"
#include "creature_icon_window.h"
#include "external_string.h"
#include "format_string.h"
#include "game_replace_keywords.h"
#include "hero.h"
#include "interface_help.h"
#include "player.h"
#include "random.h"
#include "replace_keywords.h"
#include "skill.h"
#include "skill_icon.h"
#include "skill_properties.h"
#include "standard_fonts.h"
#include "text_window.h"

extern t_external_string const		k_hotkey_buy;
extern  t_button_cache              g_cancel_button;
extern t_button_cache const         k_buy_button;
extern t_bitmap_group_cache const   k_large_material_bitmaps( "icons.materials.64" );
extern t_external_string			k_text_experience;
extern t_bitmap_group_cache			k_stat_icons_82;
extern t_bitmap_group_cache const   k_skill_frames;
static t_bitmap_group_cache const	k_tree_of_knowledge_bitmaps( "dialog.tree_of_knowledge" );

static t_external_string const		k_text_plus_1_level( "plus_1_level.tree_of_knowledge" );

/*
** School of Magic dialog constructor.
*/
t_dialog_tree_of_knowledge::t_dialog_tree_of_knowledge ( t_window* parent )
					: t_window( k_completely_transparent, parent )
{

}


void t_dialog_tree_of_knowledge::init_dialog( std::vector<t_hero*> const& heroes, std::string const& name_text, std::string const& intro_text, 
                std::string const& rejected_text, t_window* parent, t_single_use_object const& parent_object, t_army* army, int cost_type)
{
	t_screen_rect           rect;
	t_bitmap_layer const*   layer;
	t_window*               window;
	t_window*               top_window;
	t_window*               background;
	t_screen_point          origin(0,0);
	t_screen_point          point;
    int                     i;
	t_bitmap_group_ptr      material_bitmaps_ptr = k_large_material_bitmaps.get();
	t_help_block const&     material_help = get_help_block( "material_display" );
	t_help_block const&	    shared_help = get_help_block( "shared" );

    /*
    ** Set init. values.
    */
	m_bitmaps_ptr = k_tree_of_knowledge_bitmaps.get();
    m_parent_object = &parent_object;
    m_cost_type = cost_type;
	m_current_cost = 0;
	m_player_ptr = army->get_owner();
    if (m_cost_type == k_cost_2500_gold)
	    m_player_funds = m_player_ptr->get_funds()[k_gold];
    else
	    m_player_funds = m_player_ptr->get_funds()[k_gems];

	/*
    ** Create background
    */
	layer = m_bitmaps_ptr->find( "top" );
	top_window = new t_bitmap_layer_window( layer, origin, this );
	layer = m_bitmaps_ptr->find( "left" );
	window = new t_bitmap_layer_window( layer, origin, this );
	layer = m_bitmaps_ptr->find( "bottom" );
	window = new t_bitmap_layer_window( layer, origin, this );
	layer = m_bitmaps_ptr->find( "right" );
	window = new t_bitmap_layer_window( layer, origin, this );

	layer = m_bitmaps_ptr->find( "background" );
	background = new t_bitmap_layer_window( layer, origin, this );
	origin = -layer->get_rect().top_left();

    /*
    ** Show icons.  Cost icon.
    */
	point = m_bitmaps_ptr->find( "icon_1" )->get_rect().top_left() + origin;

    if (m_cost_type == k_cost_2500_gold)
    {
        layer = material_bitmaps_ptr->find ("gold");
    }
    else
    {
        layer = material_bitmaps_ptr->find ("gems");
    }
	rect = m_bitmaps_ptr->find( "icon_1" )->get_rect() + origin;
    point.x += abs((rect.width ()/2) - (layer->get_width()/2));
    
	window = new t_bitmap_layer_window( layer, point, background ); //this );
    if (m_cost_type == k_cost_2500_gold)
        set_help( window, material_help, "gold" );
    else
        set_help( window, material_help, "gems" );
    
    // Add frame.
    layer = m_bitmaps_ptr->find( "icon_1_frame" );
	window = new t_bitmap_layer_window( layer, origin, background );

    // Add experience icon.
	t_bitmap_group_ptr     bitmaps_ptr;
	t_bitmap_group_window* group_window_ptr;
    
	point = m_bitmaps_ptr->find( "icon_2" )->get_rect().top_left() + origin;
	bitmaps_ptr = k_stat_icons_82.get();
	group_window_ptr = new t_bitmap_group_window( bitmaps_ptr, point, "experience", background );
    set_help( group_window_ptr, shared_help, "experience" );
    
    /*
    ** Text windows.
    */
	t_text_window* text_window_ptr;
	std::string    text;

	text = name_text;
	rect = m_bitmaps_ptr->find( "text_title" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font( 22 ), rect, background, text, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );

	/*
    ** Add the intro text.
    */
	text = intro_text;
	rect = m_bitmaps_ptr->find( "text_dialog" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font( 22 ), rect, background, text, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );

	/*
    ** Add the experience text.
    */
	rect = m_bitmaps_ptr->find( "text_icon_2" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font( rect.height() ), rect, background, k_text_plus_1_level, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );

	/*
    ** Create hero selection portraits. 
    */
	point = m_bitmaps_ptr->find("hero_portraits")->get_rect().top_left() + origin;

	m_hero_selection_window = new t_creature_select_window( point, false, background );
	for (i = 0; i < heroes.size(); i++)
	{
		m_hero_selection_window->add( heroes[i] );

        /*
        ** Has hero visited already, or can't add more experience?
        */
        if ( heroes[i]->has_visited( parent_object ) ||  (!(heroes[i]->can_add_experience( m_player_ptr ))))
        {
		    m_hero_selection_window->enable( i, false );
            m_hero_selection_window->set_help_text( i, rejected_text);
        }
        else
        {
		    m_hero_selection_window->set_help_text( i, heroes[i]->get_name() );
            if (m_cost_type == k_cost_2500_gold)
    	        m_current_cost += k_cost_gold;
            else
    	        m_current_cost += k_cost_gems;
        }
	}
	m_hero_selection_window->select_all();
	m_hero_selection_window->set_handler( bound_handler( *this, &t_dialog_tree_of_knowledge::selection_change ));
    
    /*
    ** Add the cost text - cost of skill upgrade is 2000
    */
	rect = m_bitmaps_ptr->find( "text_icon_1" )->get_rect() + origin;
	m_cost_window_ptr = new t_text_window( get_font( rect.height() ), rect, background, format_string( "%i", m_current_cost ), 
		                             t_pixel_24(0,0,0) );
	m_cost_window_ptr->set_drop_shadow( true, t_pixel_24(200,200,200) );
	m_cost_window_ptr->set_justification( k_justify_center );

	/*
    ** Add buttons.
    */
	t_button*        button;
	t_button_handler button_handler;
	t_help_block const&		help = get_help_block( "shared" );

	point = m_bitmaps_ptr->find( "purchase_icon" )->get_rect().top_left() + origin;
	m_buy_button = new t_button( k_buy_button.get(), point, background );
	button_handler = bound_handler( *this, &t_dialog_tree_of_knowledge::buy_clicked );
	m_buy_button->set_click_handler( button_handler );
  set_help( m_buy_button, help, "buy" );

	point = m_bitmaps_ptr->find( "close_button" )->get_rect().top_left() + origin;
	button = new t_button( g_cancel_button.get(), point, background );
	button_handler = bound_handler( *this, &t_dialog_tree_of_knowledge::close_clicked );
	button->set_click_handler( button_handler );
  set_help( button , help, "cancel" );

    // Init.
    selection_change( NULL, NULL );

    /*
    ** Set the position and display the window.
    */
	t_screen_rect parent_rect = get_parent()->get_client_rect();
    
	rect = m_bitmaps_ptr->get_rect();
	rect += (parent_rect.size() - rect.size()) / 2;
	init( rect );

}

// ------------------------------------------------------------------
// Tree of Knowledge dialog
// ------------------------------------------------------------------
void t_dialog_tree_of_knowledge::selection_change( t_creature_select_window*, t_creature_stack* )
{
	int i;

	m_current_cost = 0;

	for (i = 0; i < m_hero_selection_window->get_count(); i++)
    {
		if ((m_hero_selection_window->is_selected(i)) && (m_hero_selection_window->is_enabled (i)))
        {
            if (m_cost_type == k_cost_2500_gold)
    	        m_current_cost += k_cost_gold;
            else
    	        m_current_cost += k_cost_gems;
        }
    }

    /*
    ** Set current cost of upgrades.
    */
	m_cost_window_ptr->set_text( format_string( "%i", m_current_cost ) );

    /*
    ** Disable buy button if player doesn't have sufficient funds.
    */
	if ((m_current_cost > m_player_funds) || (m_current_cost == 0)) 
    {
	    m_buy_button->enable (false);
    }
    else
    {
	    m_buy_button->enable (true);
    }
}

/*-------------------------------------------------------------------*\
** Buy clicked ...tree of knowledge's dialog
\*-------------------------------------------------------------------*/
void t_dialog_tree_of_knowledge::buy_clicked( t_button* button )
{
	int     current_level;
	int		current_exp;
	int		min_level_exp;
    int     exp_diff;
    int     i;

	m_return_value = false;
	for (i = 0; i < m_hero_selection_window->get_count(); i++)
    {
		if ((m_hero_selection_window->is_selected(i)) && (m_hero_selection_window->is_enabled (i)))
        {
	        t_hero*     hero_ptr = m_hero_selection_window->get_creature(i)->get_hero();
            
	        current_level	= hero_ptr->get_level();
			current_exp		= hero_ptr->get_experience();
			min_level_exp	= hero_ptr->get_experience(current_level);

			if (min_level_exp <= current_exp)
			{
				// Normal case gives you credit toward your next level for any progress you'd
				// already made toward the level you were just given
				exp_diff = (hero_ptr->get_experience(current_level+1) - min_level_exp);
			}
			else
			{
				// This case _shouldn't_ happen, but has been observed.  It happens
				// when you have less experience than you should for the level you
				// think you are.  We bump you up to fix the discrepancy here.
				exp_diff = (hero_ptr->get_experience(current_level+1) - current_exp);
			}
    
	        hero_ptr->add_experience( exp_diff );
	        hero_ptr->set_visited( *m_parent_object );

            // Add selected hero to upgrade list.
    		m_selected_heroes.push_back( hero_ptr );
    		m_experience_gained.push_back( exp_diff );
    	    m_return_value = true;
        }
    }
    
    if (m_cost_type == k_cost_2500_gold)
	    m_player_ptr->spend( k_gold, m_current_cost );
    else
	    m_player_ptr->spend( k_gems, m_current_cost );

	close();
}

/*-------------------------------------------------------------------*\
** Close the tree of knowledge's dialog
\*-------------------------------------------------------------------*/
void t_dialog_tree_of_knowledge::close_clicked( t_button* button )
{
	m_return_value = false;
	close();
}

std::vector<t_hero*>t_dialog_tree_of_knowledge::get_selected_heroes()
{

    return (m_selected_heroes);
}

std::vector<int>t_dialog_tree_of_knowledge::get_gained_experience()
{
    return (m_experience_gained);
}

